#include "./Ucontext.h"
#include <iostream>

using namespace std;

int schedule_t::uthread_create(Task task)
{
	int i = 0;
	for(i = 0; i < threads.size(); ++i)
	{
		if(threads[i].state == FREE){
			break;
		}
	}
	
	if(i == threads.size())
		threads.push_back(uthread_t());
	uthread_t *push = &threads[i];
	push->psche = this;
	push->state = RUNNABLE;
	push->task = std::move(task);
	
	getcontext(&push->ctx);
	push->ctx.uc_stack.ss_sp = push->stack;
	push->ctx.uc_stack.ss_size = DEFAULT_STACK_SIZE;
	push->ctx.uc_stack.ss_flags = 0;
	push->ctx.uc_link = &mainctx;
	
	makecontext(&push->ctx, (void (*)(void))(&schedule_t::uthread_func), 1, this);
	return i;
}
void schedule_t::uthread_resume(int id)
{
	if(id < 0 || id >= threads.size())
		return ;
	if (id == running_thread)
		return;
	switch(threads[id].state)
	{
		case SUSPEND:
			running_thread = id;
			threads[id].state = RUNNING;
			swapcontext(&mainctx, &threads[id].ctx);
			break;
		case RUNNABLE:
			running_thread = id;
			swapcontext(&mainctx, &threads[id].ctx);
		default:
			break;
	}
}

void schedule_t::uthread_yield() {
    if(running_thread != -1) {
        uthread_t *puth = &threads[running_thread];
        puth->state = SUSPEND;
        running_thread = -1;

        //保存当前协程的上下文，之后恢复后继续执行
        swapcontext(&puth->ctx, &mainctx);
	}
}

void schedule_t::uthread_func(void *arg)
{
	schedule_t *ps = (schedule_t*)(arg);
	int id = ps->running_thread;
	if(id != -1)
	{
		uthread_t *push = &ps->threads[id];
		push->state = RUNNING;
		push->task();
		push = &ps->threads[id];
		push->state = FREE;
		ps->running_thread = -1;
	}
}
int schedule_t::schedule_finished() const
{
	if(running_thread != -1)
		return 0;
	else
	{
		for(int i =0; i < threads.size(); ++i)
		{
			if(threads[i].state != FREE)
				return 0;
		}
	}
	return 1;
}
